<!--
 * @Author: ssj
 * @Date: 2021-08-16 10:25:16
 * @LastEditors: swc
 * @LastEditTime: 2024-12-25 16:04:13
 * @Description: oImageSelector
 *
-->
<template>
  <div class="o-image-selector">
    <div class="o-image-box">
      <div class="img-container" v-for="(el, idx) in lValue" :key="idx">
        <img
          :class="{ 'img-chked': el.checked, 'img-cursor': isView }"
          v-if="el._content_ === 'image'"
          alt="Preview"
          :src="el.url"
          :title="el.fileName"
          @click="imageCheck(idx, el, $event)"
          @load="el.revokeObjectURL()"
          @mouseenter="onMouseenter"
        />
      </div>
    </div>
    <div class="o-image-btn" v-show="!renderOpts.props.disabled">
      <input
        ref="uploadImage"
        type="file"
        multiple
        @change="onChange"
        accept=".jpg,.png,.jpeg,.bmp,.gif,.webp"
      />
      <i class="wy-icon wy-shangchuan"></i>
    </div>
    <div
      class="o-image-btn"
      @click="delImg"
      v-show="!renderOpts.props.disabled && isCanHandle"
    >
      <i class="wy-icon wy-delete"></i>
    </div>
  </div>
</template>
<script lang="ts">
import { T_srv, ts, Tsrv, vue } from '@/services';
import { N_input } from '@/types';

interface I_value extends N_input.I_fileDesc {
  url: string;
  checked: boolean;
  revokeObjectURL: () => void;
}
@T_srv.comp
export default class oImageSelector extends vue {
  @T_srv.prop() renderOpts: N_input.I_renderOpts;

  @T_srv.prop() params: any;

  public G_compName: string = 'oImageSelector';

  private G_value: N_input.I_fileValue = {
    fileLibID: '',
    files: []
  };

  // 内部渲染
  private lValue: Array<I_value> = [];

  // value
  private G_paramsFromComp: string = null;

  private G_funName: string = '';

  public isView: boolean = false;

  @T_srv.model('model-change') modelvalue: string | null;

  @T_srv.watch('modelvalue')
  private onValueChange(val: string | null): void {
    this.setValue(val);
  }

  @T_srv.watch('params')
  private onParamsChange(): void {
    this.initValue();
  }

  get isCanHandle(): boolean {
    let flag: boolean = false;
    if (this.lValue.length > 0) {
      this.lValue.forEach(v => {
        if (v.checked) {
          flag = true;
        }
      });
    }
    return flag;
  }

  created() {
    this.G_paramsFromComp = this.renderOpts.props.getTcommand()?.compName;
    if (Tsrv.noValue(this.G_paramsFromComp)) {
      this.$msg(Tsrv.getI18nByValue('未定义的组件'));
      console.error('未定义的组件');
    }
    this.init();
  }

  mounted() {}

  /**
   * @Author: ssj
   * @description: 初始化
   */
  private init(): void {
    this.G_funName = this.renderOpts.props.funName;
    if (this.G_paramsFromComp === 'oBaseGrid') {
      this.setValue(this.params.row[this.params.column.property]);
    } else {
      this.setValue(this.params.data[this.params.property]);
    }
  }

  private initValue(): void {
    if (this.lValue.length > 0) {
      return;
    }
    if (this.G_paramsFromComp === 'oBaseGrid') {
      if (!Tsrv.noValue(this.params.row[this.params.column.field])) {
        this.setValue(this.params.row[this.params.column.field]);
      }
    } else {
      if (!Tsrv.noValue(this.params.data[this.params.property])) {
        this.setValue(this.params.data[this.params.property]);
      }
    }
  }

  private onChange(e: any) {
    const upload = new ts.T_uploadArg(Tsrv.getWsCliID());
    upload.setFiles(e.target.files).setType('image');
    upload.SetRouteID(Tsrv.utils.custUUID());
    Tsrv.upLoad(upload)
      .then(([res, err]) => {
        this.$msg(err ?? res.msg);
        if (res.success) {
          const d: N_input.I_fileValue = {
            fileLibID: '',
            files: []
          };
          res.data.forEach(ele => {
            d.files.push({
              _content_: 'image',
              fileName: ele.sourceFileName,
              libFileName: ele.targetFileName
            });
          });
          if (d.files.length > 0) {
            this.setValue(d);
          }
        }
        const refUploadInput = this.$refs.uploadImage as any;
        refUploadInput.value = '';
      })
      .catch(err => {
        console.error(err.toString());
        const refUploadInput = this.$refs.uploadImage as any;
        refUploadInput.value = '';
      });
  }

  /**
   * @Author: ssj
   * @description: 重置value
   */
  public resetValue(): void {
    this.setValue(null);
  }

  public setValue(val: N_input.I_fileValue | string): void {
    const err = () => {
      this.$msg('-530,FE,90');
      console.error('json表达式不是一个数组');
    };
    if (Tsrv.utils.noValue(val)) {
      this.lValue = [];
      this.G_value = {
        fileLibID: '',
        files: []
      };
    } else if (typeof val === 'string') {
      try {
        const v: N_input.I_fileValue = JSON.parse(val) || [];
        if (typeof v !== 'object') {
          err();
        }
        this.syncValue(v);
      } catch {
        err();
      }
    } else if (typeof val === 'object') {
      this.syncValue(val);
    } else {
      err();
    }
    this.setParamsData();
    this.emitEvent('dochange');
  }

  private syncValue(val: N_input.I_fileValue) {
    val.files.forEach(el => {
      if (Tsrv.utils.noValue(this.G_value.fileLibID)) {
        this.G_value.fileLibID = val.fileLibID;
      }
      this.G_value.files.push({
        // 识别此json内容是什么内容
        _content_: el._content_,
        // 文件名
        fileName: el.fileName,
        // 文件库里的文件名
        libFileName: el.libFileName
      });
      this.lValue.push({
        // 识别此json内容是什么内容
        _content_: el._content_,
        // 文件名
        fileName: el.fileName,
        // 文件库里的文件名
        libFileName: el.libFileName,
        url: '',
        checked: false,
        revokeObjectURL: null
      });
      this.lValue.forEach(ele => {
        if (Tsrv.utils.noValue(ele.url)) {
          const dwn = new ts.T_downloadArg();
          dwn.setFileName(el.libFileName).setPath('image');
          Tsrv.download(dwn)
            .then(r => {
              if (!r.err) {
                ele.url = r.url;
                ele.revokeObjectURL = r.revokeObjectURL;
              } else {
                this.$msg(r.err);
              }
            })
            .catch(err => {
              this.$msg(err);
            });
        }
      });
    });
  }

  /**
   * @Author: ssj
   * @description: 修改表值
   */
  public setParamsData(): void {
    if (this.G_paramsFromComp === 'oBaseGrid') {
      if (this.params.column.field) {
        this.params.row[this.params.column.field] = Tsrv.utils.toJSONString(
          this.G_value
        );
      }
    } else {
      this.params.data[this.params.property] = Tsrv.utils.toJSONString(
        this.G_value
      );
    }
  }

  /**
   * @Author: ssj
   * @description: 获取value
   */
  public getValue(): any {
    return this.G_value;
  }

  /**
   * @Author: ssj
   * @param {string} event 发送事件名
   * @description: 发送事件
   */
  public emitEvent(event: string): void {
    const ev: any = this.renderOpts.events;
    const params = Tsrv.utils.cloneNoMatchVue(this.params, true);
    params.from = 'inputtext';
    for (const action in ev) {
      if (ev[action] && action === `on-${event}`) {
        ev[action](params);
      }
    }
    this.$emit('model-change', this.G_value);
    this.$emit('on-change', this.G_value);
  }

  public imageCheck(idx: number, item: N_input.I_fileValue, event: any) {
    if (Tsrv.utils.noValue(this.lValue)) {
      return;
    }
    if (this.isView) {
      Tsrv.utils.createModal('o-image-viewer', {
        imageValue: item
      });
    } else {
      this.lValue.forEach(el => {
        el.checked = false;
      });
      this.lValue[idx].checked = true;
    }
  }

  public delImg() {
    if (Tsrv.utils.noValue(this.lValue)) {
      return;
    }
    this.lValue.forEach((el, idx, arr) => {
      if (el.checked) {
        arr.splice(idx, 1);
        this.G_value.files.splice(idx, 1);
      }
    });
    this.setParamsData();
    this.emitEvent('dochange');
  }

  public onMouseenter() {
    this.isView = this.renderOpts.props.disabled;
  }
}
</script>

<style scoped lang="scss">
.o-image-selector {
  // height: 80px;
  height: 32px;
  width: 100%;
  background-color: #fff;
  display: flex;
  align-items: center;
  border-bottom: 1px solid #ccc;
  padding: 3px;
  overflow: hidden;
  .o-image-box {
    // flex: 1;
    display: flex;
    height: 100%;
    padding-right: 5px;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    .img-container {
      height: 100%;
      width: 100%;
      > img {
        height: 100%;
        width: auto;
        // cursor: zoom-in;
        padding: 2px 0 2px 0;
        margin-right: 6px;
        border: 1px solid rgb(222, 214, 214);
      }
      .img-cursor {
        cursor: zoom-in;
      }
      .img-chked {
        border: 1px solid red;
      }
    }
  }
  .o-image-btn {
    width: 23px;
    flex-shrink: 0;
    position: relative;
    height: 30px;
    display: flex;
    align-items: center;
    cursor: pointer;
    overflow: hidden;
    > i {
      width: 23px;
      cursor: pointer;
      color: var(--default-hover-font-color);
      font-size: 18px;
    }
    > input[type='file'] {
      width: 23px;
      opacity: 0;
      position: absolute;
      left: 0;
      top: 0;
      cursor: pointer;
    }
  }
}
</style>
